﻿using System;
using System.Collections.Specialized;
using System.Threading;

namespace Utils
{
    public class ReadWriteLockedObservableCollection<T> : INotifyCollectionChanged
	{
		#region Attributes

		private readonly ObservableCollection2<T> _data;
        private readonly ReaderWriterLockSlim2 _readWriteLock;

		#endregion

		#region Events

		public event NotifyCollectionChangedEventHandler CollectionChanged;

		#endregion

		#region Public Methods

		public ReadWriteLockedObservableCollection(TimeSpan maxWaitForWriteLock)
        {
            _data = new ObservableCollection2<T>();
            _data.CollectionChanged += this.OnCollectionChanged; // Local object
			_readWriteLock = new ReaderWriterLockSlim2(LockRecursionPolicy.SupportsRecursion, maxWaitForWriteLock);
        }

		public ReadWriteLockedObservableCollection(ObservableCollection2<T> data, TimeSpan maxWaitForWriteLock)
		{
			_data = data;
			_data.CollectionChanged += this.OnCollectionChanged; // Local object
			_readWriteLock = new ReaderWriterLockSlim2(LockRecursionPolicy.SupportsRecursion, maxWaitForWriteLock);
		}

        public ObservableCollection2<T> GetReadLock()
        {
            _readWriteLock.EnterReadLock();
            return _data;
        }

        public void FreeReadLock()
        {
            _readWriteLock.ExitReadLock();
        }

        public ObservableCollection2<T> GetWriteLock()
        {
            _readWriteLock.EnterWriteLock();
            return _data;
        }

        public void FreeWriteLock()
        {
            _readWriteLock.ExitWriteLock();
        }

        protected virtual void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (this.CollectionChanged != null)
            {
                this.CollectionChanged(sender, e);
            }
		}

		#endregion
	}
}
